module Admins
  class AcademicPartitionsController < ControllerBase
    before_action :set_academic_partition, only: [:show, :update, :destroy, :ancestors]
    # before_action :validate_uselessness, only: [:destroy]
    before_action :validate_plan_inactiveness, only: [:update, :destroy]
    before_action :validate_plan_inactiveness_for_create, only: [:create]

    def ancestors
      ids = AcademicPartitionHierarchy.where(descendant_id: @academic_partition.id).pluck(:ancestor_id)
      @academic_partitions = AcademicPartition.where(id: ids)
                                 .order_as_specified(type: %w(College Department Grade Klass))
      render json: @academic_partitions, each_serializer: AcademicPartitionSerializer
    end

    # GET /admins/academic_partitions
    def index
      @academic_partitions = AcademicPartition.where(parent_id: params[:parent_id])
      render json: @academic_partitions, each_serializer: AcademicPartitionSerializer
    end

    # GET /admins/academic_partitions/1
    def show
      parent_id = @academic_partition.id
      hierarchies = AcademicPartitionHierarchy.where(ancestor_id: parent_id)
                        .where.not(distance: 0)
                        .pluck(:descendant_id)

      partitions = AcademicPartition.where(id: hierarchies)
                       .select(:id, :name, :parent_id, :type)
                       .to_a
                       .map(&:attributes)
                       .group_by{|h| h['parent_id']}

      roots = partitions[parent_id]

      roots.each {|root| build_tree(root, partitions)}

      render json: roots
    end

    # POST /admins/academic_partitions
    def create
      @academic_partition = AcademicPartition.new(academic_partition_params)

      if @academic_partition.save
        # expire_cache "academic_partitions:index:#{params[:parent_id]}" do
          render json: @academic_partition, status: :created, location: [:admins, @academic_partition]
        # end
      else
        render json: @academic_partition.errors, status: :unprocessable_entity
      end
    end

    # PATCH/PUT /admins/academic_partitions/1
    def update
      if @academic_partition.update(params.permit(:name))
        # expire_cache "academic_partitions:index:#{@academic_partition.parent_id}" do
          render json: @academic_partition
        # end
      else
        render json: @academic_partition.errors, status: :unprocessable_entity
      end
    end

    # DELETE /admins/academic_partitions/1
    def destroy
      # expire_cache "academic_partitions:index:*" do
        @academic_partition.destroy
        rescue ActiveRecord::StatementInvalid
          render json: {base: ['不可删除']}, status: :unprocessable_entity
      # end
    end

    private
    # Use callbacks to share common setup or constraints between actions.
    def set_academic_partition
      @academic_partition = AcademicPartition.find(params[:id])
    end

    # Only allow a trusted parameter "white list" through.
    def academic_partition_params
      params.permit(:name, :parent_id)
    end

    def build_tree(root, partitions)
      root['children'] = partitions[root['id']] || []
      root['children'].each {|child| build_tree(child, partitions)}
    end

    def validate_uselessness
      ids = AcademicPartitionHierarchy.where(descendant_id: @academic_partition.id)
                                             .pluck(:ancestor_id)
      in_use = Target.where(academic_partition_id: ids).exists?
      render json: {base: ['正被使用']}, status: :unprocessable_entity if in_use
    end

    def validate_plan_inactiveness
      ids = AcademicPartitionHierarchy.where(descendant_id: @academic_partition.id)
                .pluck(:ancestor_id)
      in_use = Plan.joins(:targets)
                   .where('targets.academic_partition_id': ids)
                   .where(active: true).exists?
      render json: {base: ['正在缴费']}, status: :unprocessable_entity if in_use
    end

    def validate_plan_inactiveness_for_create
      ids = AcademicPartitionHierarchy.where(descendant_id: params[:parent_id])
                .pluck(:ancestor_id)
      in_use = Plan.joins(:targets)
                   .where('targets.academic_partition_id': ids)
                   .where(active: true).exists?
      render json: {base: ['正在缴费']}, status: :unprocessable_entity if in_use
    end
  end
end
